1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package scouter.javassist.bytecode;
18
19 import java.io.ByteArrayOutputStream;
20 import java.io.DataInputStream;
21 import java.io.IOException;
22 import java.util.HashMap;
23 import java.util.Map;
24
25 import scouter.javassist.bytecode.AnnotationDefaultAttribute;
26 import scouter.javassist.bytecode.AttributeInfo;
27 import scouter.javassist.bytecode.ByteArray;
28 import scouter.javassist.bytecode.ConstPool;
29 import scouter.javassist.bytecode.Descriptor;
30 import scouter.javassist.bytecode.annotation.Annotation;
31 import scouter.javassist.bytecode.annotation.AnnotationMemberValue;
32 import scouter.javassist.bytecode.annotation.AnnotationsWriter;
33 import scouter.javassist.bytecode.annotation.ArrayMemberValue;
34 import scouter.javassist.bytecode.annotation.BooleanMemberValue;
35 import scouter.javassist.bytecode.annotation.ByteMemberValue;
36 import scouter.javassist.bytecode.annotation.CharMemberValue;
37 import scouter.javassist.bytecode.annotation.ClassMemberValue;
38 import scouter.javassist.bytecode.annotation.DoubleMemberValue;
39 import scouter.javassist.bytecode.annotation.EnumMemberValue;
40 import scouter.javassist.bytecode.annotation.FloatMemberValue;
41 import scouter.javassist.bytecode.annotation.IntegerMemberValue;
42 import scouter.javassist.bytecode.annotation.LongMemberValue;
43 import scouter.javassist.bytecode.annotation.MemberValue;
44 import scouter.javassist.bytecode.annotation.ShortMemberValue;
45 import scouter.javassist.bytecode.annotation.StringMemberValue;
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 public class AnnotationsAttribute extends AttributeInfo {
127
128
129
130 public static final String visibleTag = "RuntimeVisibleAnnotations";
131
132
133
134
135 public static final String invisibleTag = "RuntimeInvisibleAnnotations";
136
137
138
139
140
141
142
143
144
145
146
147 public AnnotationsAttribute(ConstPool cp, String attrname, byte[] info) {
148 super(cp, attrname, info);
149 }
150
151
152
153
154
155
156
157
158
159
160
161
162 public AnnotationsAttribute(ConstPool cp, String attrname) {
163 this(cp, attrname, new byte[] { 0, 0 });
164 }
165
166
167
168
169 AnnotationsAttribute(ConstPool cp, int n, DataInputStream in)
170 throws IOException
171 {
172 super(cp, n, in);
173 }
174
175
176
177
178 public int numAnnotations() {
179 return ByteArray.readU16bit(info, 0);
180 }
181
182
183
184
185 public AttributeInfo copy(ConstPool newCp, Map classnames) {
186 Copier copier = new Copier(info, constPool, newCp, classnames);
187 try {
188 copier.annotationArray();
189 return new AnnotationsAttribute(newCp, getName(), copier.close());
190 }
191 catch (Exception e) {
192 throw new RuntimeException(e);
193 }
194 }
195
196
197
198
199
200
201
202
203
204
205 public Annotation getAnnotation(String type) {
206 Annotation[] annotations = getAnnotations();
207 for (int i = 0; i < annotations.length; i++) {
208 if (annotations[i].getTypeName().equals(type))
209 return annotations[i];
210 }
211
212 return null;
213 }
214
215
216
217
218
219
220
221 public void addAnnotation(Annotation annotation) {
222 String type = annotation.getTypeName();
223 Annotation[] annotations = getAnnotations();
224 for (int i = 0; i < annotations.length; i++) {
225 if (annotations[i].getTypeName().equals(type)) {
226 annotations[i] = annotation;
227 setAnnotations(annotations);
228 return;
229 }
230 }
231
232 Annotation[] newlist = new Annotation[annotations.length + 1];
233 System.arraycopy(annotations, 0, newlist, 0, annotations.length);
234 newlist[annotations.length] = annotation;
235 setAnnotations(newlist);
236 }
237
238
239
240
241
242
243
244
245
246
247 public Annotation[] getAnnotations() {
248 try {
249 return new Parser(info, constPool).parseAnnotations();
250 }
251 catch (Exception e) {
252 throw new RuntimeException(e);
253 }
254 }
255
256
257
258
259
260
261
262
263 public void setAnnotations(Annotation[] annotations) {
264 ByteArrayOutputStream output = new ByteArrayOutputStream();
265 AnnotationsWriter writer = new AnnotationsWriter(output, constPool);
266 try {
267 int n = annotations.length;
268 writer.numAnnotations(n);
269 for (int i = 0; i < n; ++i)
270 annotations[i].write(writer);
271
272 writer.close();
273 }
274 catch (IOException e) {
275 throw new RuntimeException(e);
276 }
277
278 set(output.toByteArray());
279 }
280
281
282
283
284
285
286
287
288 public void setAnnotation(Annotation annotation) {
289 setAnnotations(new Annotation[] { annotation });
290 }
291
292
293
294
295
296 void renameClass(String oldname, String newname) {
297 HashMap map = new HashMap();
298 map.put(oldname, newname);
299 renameClass(map);
300 }
301
302 void renameClass(Map classnames) {
303 Renamer renamer = new Renamer(info, getConstPool(), classnames);
304 try {
305 renamer.annotationArray();
306 } catch (Exception e) {
307 throw new RuntimeException(e);
308 }
309 }
310
311 void getRefClasses(Map classnames) { renameClass(classnames); }
312
313
314
315
316 public String toString() {
317 Annotation[] a = getAnnotations();
318 StringBuilder sbuf = new StringBuilder();
319 int i = 0;
320 while (i < a.length) {
321 sbuf.append(a[i++].toString());
322 if (i != a.length)
323 sbuf.append(", ");
324 }
325
326 return sbuf.toString();
327 }
328
329 static class Walker {
330 byte[] info;
331
332 Walker(byte[] attrInfo) {
333 info = attrInfo;
334 }
335
336 final void parameters() throws Exception {
337 int numParam = info[0] & 0xff;
338 parameters(numParam, 1);
339 }
340
341 void parameters(int numParam, int pos) throws Exception {
342 for (int i = 0; i < numParam; ++i)
343 pos = annotationArray(pos);
344 }
345
346 final void annotationArray() throws Exception {
347 annotationArray(0);
348 }
349
350 final int annotationArray(int pos) throws Exception {
351 int num = ByteArray.readU16bit(info, pos);
352 return annotationArray(pos + 2, num);
353 }
354
355 int annotationArray(int pos, int num) throws Exception {
356 for (int i = 0; i < num; ++i)
357 pos = annotation(pos);
358
359 return pos;
360 }
361
362 final int annotation(int pos) throws Exception {
363 int type = ByteArray.readU16bit(info, pos);
364 int numPairs = ByteArray.readU16bit(info, pos + 2);
365 return annotation(pos + 4, type, numPairs);
366 }
367
368 int annotation(int pos, int type, int numPairs) throws Exception {
369 for (int j = 0; j < numPairs; ++j)
370 pos = memberValuePair(pos);
371
372 return pos;
373 }
374
375
376
377
378 final int memberValuePair(int pos) throws Exception {
379 int nameIndex = ByteArray.readU16bit(info, pos);
380 return memberValuePair(pos + 2, nameIndex);
381 }
382
383
384
385
386 int memberValuePair(int pos, int nameIndex) throws Exception {
387 return memberValue(pos);
388 }
389
390
391
392
393 final int memberValue(int pos) throws Exception {
394 int tag = info[pos] & 0xff;
395 if (tag == 'e') {
396 int typeNameIndex = ByteArray.readU16bit(info, pos + 1);
397 int constNameIndex = ByteArray.readU16bit(info, pos + 3);
398 enumMemberValue(pos, typeNameIndex, constNameIndex);
399 return pos + 5;
400 }
401 else if (tag == 'c') {
402 int index = ByteArray.readU16bit(info, pos + 1);
403 classMemberValue(pos, index);
404 return pos + 3;
405 }
406 else if (tag == '@')
407 return annotationMemberValue(pos + 1);
408 else if (tag == '[') {
409 int num = ByteArray.readU16bit(info, pos + 1);
410 return arrayMemberValue(pos + 3, num);
411 }
412 else {
413 int index = ByteArray.readU16bit(info, pos + 1);
414 constValueMember(tag, index);
415 return pos + 3;
416 }
417 }
418
419
420
421
422 void constValueMember(int tag, int index) throws Exception {}
423
424
425
426
427 void enumMemberValue(int pos, int typeNameIndex, int constNameIndex)
428 throws Exception {
429 }
430
431
432
433
434 void classMemberValue(int pos, int index) throws Exception {}
435
436
437
438
439 int annotationMemberValue(int pos) throws Exception {
440 return annotation(pos);
441 }
442
443
444
445
446 int arrayMemberValue(int pos, int num) throws Exception {
447 for (int i = 0; i < num; ++i) {
448 pos = memberValue(pos);
449 }
450
451 return pos;
452 }
453 }
454
455 static class Renamer extends Walker {
456 ConstPool cpool;
457 Map classnames;
458
459
460
461
462
463
464
465
466
467
468 Renamer(byte[] info, ConstPool cp, Map map) {
469 super(info);
470 cpool = cp;
471 classnames = map;
472 }
473
474 int annotation(int pos, int type, int numPairs) throws Exception {
475 renameType(pos - 4, type);
476 return super.annotation(pos, type, numPairs);
477 }
478
479 void enumMemberValue(int pos, int typeNameIndex, int constNameIndex)
480 throws Exception
481 {
482 renameType(pos + 1, typeNameIndex);
483 super.enumMemberValue(pos, typeNameIndex, constNameIndex);
484 }
485
486 void classMemberValue(int pos, int index) throws Exception {
487 renameType(pos + 1, index);
488 super.classMemberValue(pos, index);
489 }
490
491 private void renameType(int pos, int index) {
492 String name = cpool.getUtf8Info(index);
493 String newName = Descriptor.rename(name, classnames);
494 if (!name.equals(newName)) {
495 int index2 = cpool.addUtf8Info(newName);
496 ByteArray.write16bit(index2, info, pos);
497 }
498 }
499 }
500
501 static class Copier extends Walker {
502 ByteArrayOutputStream output;
503 AnnotationsWriter writer;
504 ConstPool srcPool, destPool;
505 Map classnames;
506
507
508
509
510
511
512
513
514
515
516
517
518 Copier(byte[] info, ConstPool src, ConstPool dest, Map map) {
519 this(info, src, dest, map, true);
520 }
521
522 Copier(byte[] info, ConstPool src, ConstPool dest, Map map, boolean makeWriter) {
523 super(info);
524 output = new ByteArrayOutputStream();
525 if (makeWriter)
526 writer = new AnnotationsWriter(output, dest);
527
528 srcPool = src;
529 destPool = dest;
530 classnames = map;
531 }
532
533 byte[] close() throws IOException {
534 writer.close();
535 return output.toByteArray();
536 }
537
538 void parameters(int numParam, int pos) throws Exception {
539 writer.numParameters(numParam);
540 super.parameters(numParam, pos);
541 }
542
543 int annotationArray(int pos, int num) throws Exception {
544 writer.numAnnotations(num);
545 return super.annotationArray(pos, num);
546 }
547
548 int annotation(int pos, int type, int numPairs) throws Exception {
549 writer.annotation(copyType(type), numPairs);
550 return super.annotation(pos, type, numPairs);
551 }
552
553 int memberValuePair(int pos, int nameIndex) throws Exception {
554 writer.memberValuePair(copy(nameIndex));
555 return super.memberValuePair(pos, nameIndex);
556 }
557
558 void constValueMember(int tag, int index) throws Exception {
559 writer.constValueIndex(tag, copy(index));
560 super.constValueMember(tag, index);
561 }
562
563 void enumMemberValue(int pos, int typeNameIndex, int constNameIndex)
564 throws Exception
565 {
566 writer.enumConstValue(copyType(typeNameIndex), copy(constNameIndex));
567 super.enumMemberValue(pos, typeNameIndex, constNameIndex);
568 }
569
570 void classMemberValue(int pos, int index) throws Exception {
571 writer.classInfoIndex(copyType(index));
572 super.classMemberValue(pos, index);
573 }
574
575 int annotationMemberValue(int pos) throws Exception {
576 writer.annotationValue();
577 return super.annotationMemberValue(pos);
578 }
579
580 int arrayMemberValue(int pos, int num) throws Exception {
581 writer.arrayValue(num);
582 return super.arrayMemberValue(pos, num);
583 }
584
585
586
587
588
589
590
591
592
593
594 int copy(int srcIndex) {
595 return srcPool.copy(srcIndex, destPool, classnames);
596 }
597
598
599
600
601
602
603
604
605
606
607
608 int copyType(int srcIndex) {
609 String name = srcPool.getUtf8Info(srcIndex);
610 String newName = Descriptor.rename(name, classnames);
611 return destPool.addUtf8Info(newName);
612 }
613 }
614
615 static class Parser extends Walker {
616 ConstPool pool;
617 Annotation[][] allParams;
618 Annotation[] allAnno;
619 Annotation currentAnno;
620 MemberValue currentMember;
621
622
623
624
625
626
627
628
629 Parser(byte[] info, ConstPool cp) {
630 super(info);
631 pool = cp;
632 }
633
634 Annotation[][] parseParameters() throws Exception {
635 parameters();
636 return allParams;
637 }
638
639 Annotation[] parseAnnotations() throws Exception {
640 annotationArray();
641 return allAnno;
642 }
643
644 MemberValue parseMemberValue() throws Exception {
645 memberValue(0);
646 return currentMember;
647 }
648
649 void parameters(int numParam, int pos) throws Exception {
650 Annotation[][] params = new Annotation[numParam][];
651 for (int i = 0; i < numParam; ++i) {
652 pos = annotationArray(pos);
653 params[i] = allAnno;
654 }
655
656 allParams = params;
657 }
658
659 int annotationArray(int pos, int num) throws Exception {
660 Annotation[] array = new Annotation[num];
661 for (int i = 0; i < num; ++i) {
662 pos = annotation(pos);
663 array[i] = currentAnno;
664 }
665
666 allAnno = array;
667 return pos;
668 }
669
670 int annotation(int pos, int type, int numPairs) throws Exception {
671 currentAnno = new Annotation(type, pool);
672 return super.annotation(pos, type, numPairs);
673 }
674
675 int memberValuePair(int pos, int nameIndex) throws Exception {
676 pos = super.memberValuePair(pos, nameIndex);
677 currentAnno.addMemberValue(nameIndex, currentMember);
678 return pos;
679 }
680
681 void constValueMember(int tag, int index) throws Exception {
682 MemberValue m;
683 ConstPool cp = pool;
684 switch (tag) {
685 case 'B' :
686 m = new ByteMemberValue(index, cp);
687 break;
688 case 'C' :
689 m = new CharMemberValue(index, cp);
690 break;
691 case 'D' :
692 m = new DoubleMemberValue(index, cp);
693 break;
694 case 'F' :
695 m = new FloatMemberValue(index, cp);
696 break;
697 case 'I' :
698 m = new IntegerMemberValue(index, cp);
699 break;
700 case 'J' :
701 m = new LongMemberValue(index, cp);
702 break;
703 case 'S' :
704 m = new ShortMemberValue(index, cp);
705 break;
706 case 'Z' :
707 m = new BooleanMemberValue(index, cp);
708 break;
709 case 's' :
710 m = new StringMemberValue(index, cp);
711 break;
712 default :
713 throw new RuntimeException("unknown tag:" + tag);
714 }
715
716 currentMember = m;
717 super.constValueMember(tag, index);
718 }
719
720 void enumMemberValue(int pos, int typeNameIndex, int constNameIndex)
721 throws Exception
722 {
723 currentMember = new EnumMemberValue(typeNameIndex,
724 constNameIndex, pool);
725 super.enumMemberValue(pos, typeNameIndex, constNameIndex);
726 }
727
728 void classMemberValue(int pos, int index) throws Exception {
729 currentMember = new ClassMemberValue(index, pool);
730 super.classMemberValue(pos, index);
731 }
732
733 int annotationMemberValue(int pos) throws Exception {
734 Annotation anno = currentAnno;
735 pos = super.annotationMemberValue(pos);
736 currentMember = new AnnotationMemberValue(currentAnno, pool);
737 currentAnno = anno;
738 return pos;
739 }
740
741 int arrayMemberValue(int pos, int num) throws Exception {
742 ArrayMemberValue amv = new ArrayMemberValue(pool);
743 MemberValue[] elements = new MemberValue[num];
744 for (int i = 0; i < num; ++i) {
745 pos = memberValue(pos);
746 elements[i] = currentMember;
747 }
748
749 amv.setValue(elements);
750 currentMember = amv;
751 return pos;
752 }
753 }
754 }